package com.xindacloud.sms.portal.config;


import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.xindacloud.sms.portal.constant.SessionKeys;
import com.xindacloud.sms.portal.handler.SmsRestTemplateErrorHandler;
import com.xindacloud.sms.portal.properties.EndpointProperties;
import com.xindacloud.sms.portal.properties.ThreadPoolProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
import org.springframework.session.web.http.HttpSessionIdResolver;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.*;

import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@Slf4j
@Configuration
@EnableConfigurationProperties({EndpointProperties.class, ThreadPoolProperties.class})
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("${server.error.path:${error.path:/error}}")
    private String errorPath;

    @Autowired
    ThreadPoolProperties threadPoolProperties;

    @Bean
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        template.setValueSerializer(new StringRedisSerializer());
        template.setDefaultSerializer(new StringRedisSerializer());
        return template;
    }

    @Bean
    public HttpSessionIdResolver httpSessionStrategy() {
        return new HeaderHttpSessionIdResolver(SessionKeys.SMS_TOKEN);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        return restTemplateBuilder
                //Response status code 4XX or 5XX to the client.
                .errorHandler(new SmsRestTemplateErrorHandler())
                .build();

    }

    @Bean
    public ExecutorService executorService() {
        return Executors.newFixedThreadPool(threadPoolProperties.getMaxThread());
    }


    @Bean
    public DefaultKaptcha captchaProducer() {

        DefaultKaptcha captchaProducer = new DefaultKaptcha();
        Properties properties = new Properties();

        properties.setProperty("kaptcha.textproducer.char.length", "4");
        properties.setProperty("kaptcha.textproducer.font.size", "46");
        properties.setProperty("kaptcha.textproducer.font.color", "1,137,255");
        properties.setProperty("kaptcha.border", "no");
        properties.setProperty("kaptcha.textproducer.font.names", "DejaVu Serif");
        properties.setProperty("kaptcha.background.clear.from", "white");
        properties.setProperty("kaptcha.background.clear.to", "white");
        properties.setProperty("kaptcha.noise.color", "1,137,255");
        properties.setProperty("kaptcha.textproducer.char.space", "12");
        properties.setProperty("kaptcha.textproducer.char.string", "0123456789SKPRHAM");

        Config config = new Config(properties);
        captchaProducer.setConfig(config);

        return captchaProducer;
    }


    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(60 * 60 * 24 * 30L);
        config.addExposedHeader(SessionKeys.SMS_TOKEN);
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                .addInterceptor(new AuthIntercept())
                .addPathPatterns("/**")
                .excludePathPatterns("/api/v1/portal/user/verification-code")
                .excludePathPatterns("/api/v1/portal/sms/open/submit")
                .excludePathPatterns("/api/v1/portal/sms/open/submit/yy")
                .excludePathPatterns("/api/v1/portal/sms/report/open/list")
                .excludePathPatterns("/api/v1/portal/user/login", "/api/v1/portal/user/login-out", "/api/v1/portal/user/registerUser")
                .excludePathPatterns("/api/v1/sms-ui-content/**", "/api/v1/sms-api/**")
                .excludePathPatterns("/webhooks/delivery-report","/sinch/delivery-report","/cm/delivery-report","/domestic/api/sms/report")
                .excludePathPatterns("/huoxin/delivery-report")
                .excludePathPatterns(errorPath)
                .excludePathPatterns("/test")
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");

    }


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Override
    public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false);
    }

}
